use std::fmt::Debug;

use anyhow::anyhow;
use serde::{Deserialize, Serialize};

use crate::SQLX;

pub mod sys_menu;
pub mod sys_role;
pub mod sys_role_menu;
pub mod sys_user;
pub mod sys_user_role;
pub mod sys_org;
//pub mod macro_crud;

#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
pub struct Page<T: Sync + Send> {
    pub(crate) items: Vec<T>,
    pub(crate) total_count: i64,
    pub(crate) page_count: i64,
}

#[derive(Debug)]
pub struct PaginationOptions {
    pub(crate) page_no: Option<i64>,
    pub(crate) page_size: Option<i64>,
}


async fn fetch_total_count(query: &str) -> anyhow::Result<i64> {
    // 构建获取总数的 SQL 查询语句
    let sqlx = SQLX.get().ok_or(anyhow!("db error"))?;
    let mut db = sqlx.acquire().await?;
    let count_query = format!("SELECT COUNT(*) FROM ({}) AS count_query", query);
    // 执行查询并获取结果
    let count: (i64,) = sqlx::query_as(&count_query)
        .fetch_one(&mut *db)
        .await?;
    Ok(count.0)
}

async fn fetch_items_with_pagination<T: Sync + Send + Unpin + for<'r> sqlx::FromRow<'r, sqlx::sqlite::SqliteRow> + for<'r> sqlx::FromRow<'r, sqlx::sqlite::SqliteRow>>(query: &str, options: &PaginationOptions) -> anyhow::Result<Vec<T>>
where
{
    let offset = (options.page_no.unwrap_or(1) - 1) * options.page_size.unwrap_or(10);
    let sqlx = SQLX.get().ok_or(anyhow!("db error"))?;
    let mut db = sqlx.acquire().await?;
    // 构建带有 LIMIT 和 OFFSET 的分页查询语句
    let paginated_query = format!("{} LIMIT {} OFFSET {}", query, options.page_size.unwrap_or(10), offset);
    // 执行查询
    println!("分页sql = {}", &paginated_query);
    let items: Vec<T> = sqlx::query_as(&paginated_query)
        .fetch_all(&mut *db)
        .await?;

    Ok(items)
}

pub async fn fetch_page<T: Serialize + Debug + Send + Sync + Unpin + for<'r> sqlx::FromRow<'r, sqlx::sqlite::SqliteRow>>(query: &str, options: &PaginationOptions) -> anyhow::Result<Page<T>> {
    // 获取总记录数
    let total_count = fetch_total_count(query).await?;

    // 执行分页查询
    let items = fetch_items_with_pagination(query, options).await?;
    // 构建 Page 结构体
    let page = Page {
        items,
        total_count,
        page_count: (total_count + options.page_size.unwrap_or(10) - 1) / options.page_size.unwrap_or(10),
    };

    Ok(page)
}
